/*
 *  Camera.h
 *  Ray Tracing
 *
 *  Created by Jean-Marc Comby + Romain Dequesne on Fri May 14 2004.
 *  Copyright (c) 2004. All rights reserved.
 *  
 *  Antialiasing par Johan Luisier (c) 2005
 *
 *  Camera
 */

#ifndef _CAMERA_H
#define _CAMERA_H
#include "Algebre/Coord.hpp"
#include "Algebre/Vecteur.hpp"

#include "Image/Image.hpp"

#include "Rayon.hpp"
#include "Environnement.hpp"


#include <iostream>
//#include <vector>

#include <boost/progress.hpp>

class Capteur;
class Cellule;

/**
 * Type d'antialiasing disponibles.
 */
enum Antialiasing
  {
    non,          /**< Aucun. */
    simple,       /**< Antialiasing 4x. */
    bourrin,      /**< Antialiasing 5x. */
    ultra_bourrin /**< Antialiasing 9x. */
  };

class Environnement;
class ElementDOM;

/**
 * Classe implémentant la caméra pour le raytracing, qui permet de
 * réaliser les prises de vues. La Camera possède un Ecran, sur lequel
 * est projetée la scene.
 *
 * @author Jean-Marc Comby + Romain Dequesne
 * @author Johan "Solo" Luisier
 *
 * @date 14 Mai 2004
 */
class Camera
{
 public:
  //constructeurs et destructeurs
  Camera();
  Camera(const Coord &, const VecteurU&, const VecteurU&, const double&,
	 Image *, Environnement*, unsigned const int &, const double &,
	 const int &);
  //Camera(const std::vector< const ElementDOM* >& structLue);
  virtual ~Camera();
  void genereImage();
  void setPosition(const Coord &);
  const Coord& position() const;
  void setDirection(const Vecteur&);
  const VecteurU& direction() const;
  void setHauteur(const Vecteur&);
  const VecteurU& hauteur() const;
  void setDistance(const double&);
  const double& distance() const;
  void env(Environnement*);
  void setPrecision(const unsigned&);
  const unsigned& precision() const;
  void setLargeur();
  const VecteurU& largeur() const;
  void setFilm(Image*);
  Image* film();
  void setAlias(const unsigned &);
  const Antialiasing& alias() const;
  void setNbrPasses( const unsigned& nbr );
  const unsigned& nbrPasses() const;
  void setFacteurOversampling( const unsigned& facteur );
  const unsigned& facteurOversampling() const;
  inline const bool& renduPrimaire() const { return RenduPrimaire; }
  
	
 private:
  /** La classe Cellule doit pouvoir accéder aux membres de Camera.
   */
  friend class Cellule;
  friend class Capteur;
  /**
   * Position du point focal.
   */
  Coord Position; //position du pt focal
  /**
   * Direction dans laquelle pointe la caméra.
   */
  VecteurU Direction; //direction de la hauteur de l'image
  /**
   * Direction de la hauteur de l'image.
   */
  VecteurU Hauteur; //ortho a dir
  /**
   * Direction de la largeur de l'image, construite de manière à être
   * orthogonale à la direction et la hauteur.
   */
  VecteurU Largeur; //otho a dir et haut
  /**
   * Distance entre le point focal et le plan de l'image.
   */
  double Distance; //distance entre pt focal et plan de l'image
  /**
   * Pointeur sur l'Environnement que l'on veut "photographier"-
   */
  Environnement* Env;
  /**
   * Profondeur de l'appel récursif, détermine la qualité des
   * réflexions.
   */
  unsigned Precision; //profondeur de l'appel recursif
  /**
   * Pointeur sur l'image à générer.
   */
  Image *Film;
  /* Ajouts de Johan, pour implémenter un anticrénelage */
  /**
   * Pointeur sur l'image intermédiaire, utilisée pour le rendu
   * primaire. Cette image peut ëtre plus grande que celle pointée par
   * Film (si FacteurOversampling \f$ > 1 \f$).
   */
  Image *SuperFilm;
  /**
   * Grandeur déterminant la précision des comparaison.
   */
  static const double eps;
  /**
   * Type d'antialiasing à utiliser pour lisser l'image.
   */
  Antialiasing Anti;
  /**
   * Seuil de détection des pixels à antialiaser.
   */
  double Seuil;
  /**
   * Compte le nombre de pixels qui ont été antialiasés.
   */
  unsigned Compteur;
  /**
   * Nombre de passes de post-rendu à effectuer.
   */
  unsigned NbrPasses;
  /**
   * Facteur d'oversampling.
   */
  unsigned FacteurOversampling;
  /** @brief Conteneut permettant de savoir si le pixel doit être antialiasé:
   * l'élément correspondant est alors @c true.
   */
  std::vector< std::vector< bool > > Contour;
  /** @brief Contient @c true s'il s'agit du rendu primaire.
   */
  bool RenduPrimaire;
  /** Instance(s) de Cellule responsable(s) du rendu de l'image.
   */
  std::vector< Cellule* > Cellules;
  std::vector< Capteur* > Capteurs;
  /** Barre de progression.
   */
  boost::progress_display * BarreProgression;
  void postRendu();
  void determinerContour();
  void determinerDirections( std::vector< VecteurU >& directions, const double& x, const double& y ) const;
  void reduireImage( const unsigned& iFinal, const unsigned& jFinal,
		     std::vector< Couleur >& couleurs ) const;
  void incrementeProgression();
  
};

#endif
